/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SMART_SERVE_SERVICES_SERVER_SESSION_SESSION_H
#define SMART_SERVE_SERVICES_SERVER_SESSION_SESSION_H

#include "assertion.h"
#include "scheduler/event.h"
#include "session/adapter.h"
#include "session/res_config.h"
#include "task.h"
#include <condition_variable>
#include <list>
#include <mutex>
#include <thread>

namespace OHOS {
namespace SmartServe {

class Model;

class Session {
public:
    Session(std::unique_ptr<SessionAdapter> adapter) : adapter_(std::move(adapter))
    {
        thread_ = std::thread([this]() { ThreadMain(); });
        resConfigs_ = adapter_->InitialResConfigs();
    }

    ~Session()
    {
        ASSERT(!thread_.joinable() && "Must call `WaitForTerminated` before destruction");
    }

    // 终止

    void AsyncTerminate() // 内部加 Session 锁
    {
        {
            std::unique_lock<std::mutex> lock(mutex_);
            terminating_ = true;
        }
        cv_.notify_all();
    }

    void WaitForTerminated() // 无需加锁
    {
        ASSERT(terminating_ && "Must call `AsyncTerminate` before `WaitForTerminated`");
        thread_.join();
    }

    // 管理结构

    void AddModel(Model* model) // 要求加管理锁
    {
        models_.push_back(model);
    }

    bool RemoveModel(Model* model) // 要求加管理锁
    {
        for (auto it = models_.begin(); it != models_.end(); ++it) {
            if (*it == model) {
                models_.erase(it);
                return true;
            }
        }
        return false;
    }

    std::vector<Model*> models_; // 无需加锁（初始化后，不会被修改）

    // 信息查询

    const std::string& Name() const // 无需加锁
    {
        return adapter_->Name();
    }

    SessionAdapter* Adapter() const // 无需加锁
    {
        return adapter_.get();
    }

    // 工作

    void AddTask(std::shared_ptr<EvalTask> task) // 内部加 Session 锁
    {
        {
            std::unique_lock<std::mutex> lock(mutex_);
            tasks_.push_back(std::move(task));
        }
        cv_.notify_all();
    }

    // ----- mutex_ 保护区 -----
    std::mutex mutex_;
    std::condition_variable cv_;
    std::list<std::shared_ptr<EvalTask>> tasks_; // 同步事件 - 推理任务
    std::atomic_bool terminating_{false};        // 异步事件 - 终止
    std::atomic_bool pending_{false};            // 异步事件 - Session 资源变更
    SessionResConfig pendingResConfig_;
    SessionResConfig currentResConfig_;

    std::vector<SessionResConfig> resConfigs_;
    // ----- mutex_ 保护区 -----

    // 对 Scheduler 接口

    SessionResConfig conservativeResConfig() const; // 要求加 Session 锁

    bool isRunnable() const; // 要求加 Session 锁

    void TriggerPending(const SessionResConfig& newResConfig); // 要求加 Session 锁
    void TriggerTerminating();                                 // 要求加管理锁

private:
    void ThreadMain();

    void HandlePending();
    void FinishPendingUse(const SessionApplyResult& result);

    void HandleTask();
    bool isCurrentlyRunnable() const;
    void AbortAllTasks();

    void HandleFinalize();

    std::thread thread_;

    std::unique_ptr<SessionAdapter> adapter_;
};

} // namespace SmartServe
} // namespace OHOS

#endif // SMART_SERVE_SERVICES_SERVER_SESSION_SESSION_H